package com.qf.scms.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.qf.scms.dao.UserDao;
import com.qf.scms.entity.User;
import com.qf.scms.node.UserNode;
import com.qf.scms.param.LoginParam;
import com.qf.scms.param.RegisterParam;
import com.qf.scms.service.LoginService;
import com.qf.scms.utils.JwtUtils;
import com.qf.scms.utils.Neo4jUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author GaoQiangLiang
 * @date 2025-06-24 20:51
 */

@Service
public class LoginServiceImpl implements LoginService {

    @Resource
    private UserDao userDao;

    @Resource
    private ThreadPoolExecutor threadPoolExecutor;

    @Resource
    private Neo4jUtils neo4jUtils;

    /**
     * 登录
     *
     * @param loginParam 登录参数
     * @return token令牌
     */
    @Override
    public String login(LoginParam loginParam) {
        // 检查用户名和密码是否为空
        if (StringUtils.isEmpty(loginParam.getUsername()) || StringUtils.isEmpty(loginParam.getPassword())) {
            throw new RuntimeException("用户名或密码不能为空");
        }

        // 判断用户名和密码
        User user = userDao.queryByUsernameAndPassword(loginParam.getUsername(), loginParam.getPassword());

        if (user == null) {
            throw new RuntimeException("用户名或密码错误");
        }

        if (user != null && user.getRole() != loginParam.getRole()) {
            throw new RuntimeException("用户角色错误");
        }

        // 生成jwt令牌
        Map<String, Object> map = new HashMap<>();
        // 将用户的信息存放到jwtToken中，便于后边使用
        map.put("uid", user.getId());
        map.put("role", user.getRole());
        map.put("username", user.getUsername());
        return JwtUtils.createJwt(map);
    }

    /**
     * 注册
     *
     * @param registerParam 注册参数
     * @return 是否注册成功
     */
    @Override
    public Boolean register(RegisterParam registerParam) {
        // 判空
        // if (registerParam.getPhone() == null || registerParam.getPhone().equals("")) {
        //     throw new RuntimeException("必须设置手机号");
        // }
        if (!StringUtils.hasLength(registerParam.getUsername())) {
            throw new RuntimeException("用户名不能为空");
        }
        // .....

        // 手机号或者用户名是否唯一
        User user1 = userDao.queryByUsername(registerParam.getUsername());
        if (user1 != null) {
            throw new RuntimeException("用户名已存在");
        }
        // boolean exists = userMapper.exists(Wrappers.lambdaQuery(User.class)
        //         .eq(User::getPhone, registerParam.getPhone()));
        // if (exists) {
        //     throw new RuntimeException("手机号已存在");
        // }

        // 手机验证码的判断


        // 邀请码是否过期和是否有效？
        User userParent = userDao.selectOneByInviteCode(registerParam.getInviteCode());
        if (userParent == null) {
            // 如果查询的邀请码对象用户为空，则说明邀请码不存在
            // 如果查询的用户邀请码已过期，则也抛出异常
            throw new RuntimeException("邀请码错误");
        }

        User user = new User();
        // 对象间同名属性的拷贝
        BeanUtils.copyProperties(registerParam, user);


        // 设置父id
        user.setId(userParent.getId());

        // 借助hutool工具，生成长度为6位的随机字符串作为邀请码
        String inviteCode = RandomUtil.randomString(6);
        // 业务逻辑:判断邀请码是否重复
        // 如果重复，重试3次，如果还重复，进行补偿处理
        if (userParent.getInviteCode().equals(inviteCode)) {
            // 本例抛出异常，实际也可以重新多次生成
            throw new RuntimeException("邀请码重复");
        }

        user.setInviteCode(inviteCode);
        int result = userDao.insert(user);


        // 假如neo4j的执行结果，不影响注册的结果，为了提高注册接口的执行效率
        // 可以考虑异步执行图数据库的操作
        UserNode pnode = neo4jUtils.getUserNode(userParent.getId());
        if (pnode == null) {
            pnode = new UserNode();
            pnode.setId(userParent.getId());
            pnode.setName(userParent.getUsername());
        }
        UserNode cnode = new UserNode();
        cnode.setId(user.getId());
        cnode.setName(user.getUsername());

        neo4jUtils.addNode(pnode, cnode);

        // 如果通过线程异步处理逻辑报错了，根据实际的业务，可以启动补偿机制
        // threadPoolExecutor.execute(() -> {
        //     // 将用户信息添加到neo4j
        //     UserNode pnode = neo4jUtils.getUserNode(userParent.getId());
        //     if (pnode == null) {
        //         pnode = new UserNode();
        //         pnode.setId(userParent.getId());
        //         pnode.setName(userParent.getUsername());
        //     }
        //     UserNode cnode = new UserNode();
        //     cnode.setId(user.getId());
        //     cnode.setName(user.getUsername());
        //
        //     neo4jUtils.addNode(pnode, cnode);
        // });

        return result > 0;
    }
}
